/****************************************************************************/
/*
*define api for xml internal parse.
*/
/****************************************************************************/

#ifndef _CMS_MDM_H
#define _CMS_MDM_H

#include <arpa/inet.h>

//#define XML_TEST_DEBUG

#define ATTR_OBJECTNODE	(1 << 0)		/*run time/compiler time both use, no store at xml*/
#define ATTR_INDEXNODE	(1 << 1)		/*run time use, compiler time mark, store both xml*/
#define ATTR_INDEXCHILD	(1 << 2)		/*compiler time use, no store at xml*/
#define ATTR_NODECONFIGURED	(1 << 3)	/*run time use, no store at xml, means this node has been configured and need to save*/
#define ATTR_ALWAYSACTIVE	(1 << 4)	/*for some special case, ex. tr069, the index child nodes need to active at default
										run time/compiler time both use, no store at xml*/
#ifdef CMS_XML_PARSE_PHASE_1
#define ATTR_FILTERMATCHNODE	(1 << 5)	/*compile and run time use, mark nodes that appear in filter.xml*/
#define ATTR_FILTERONLYNODE		(1 << 6)	/*complie time use, if the src node has this attribute, the dst node will only copy object offset of src node.*/
#define ATTR_FILTEREVERYNODE	(1 << 7)	/*complie and run time use, for distinguish src node that dst node needs independent object space in ATTR_FILTERONLYNODE node.*/
#endif
/*
remove ATTR_NODENEEDSAVE, every node need to be save to config.xml, even though only non-configured
parameters have been configured.
*/

#define LAST_NAME_FOUND	(1 << 31)	/*use name len last bit to check last name or not*/

#ifdef SYSDEF_PARSER_ON_HOST
#ifndef	BIGENDIAN
#define HTONS(s)		(s)
#define HTONL(l)		(l)
#define HTONDL(l)		(l)
#define NTOHS(s)		(s)
#define NTOHL(l)		(l)
#define NTOHDL(l)		(l)
#else
/*for cmsoffset_t, if we move to 64 bits, then ntohl should change to 64 bits*/
#define NTOHDL(x)	ntohl(x)
#define NTOHL(x)	ntohl(x)
#define NTOHS(x)	ntohs(x)
#define HTONDL(x)	htonl(x)
#define HTONL(x)	htonl(x)
#define HTONS(x)	htons(x)
#endif
#else

#define HTONS(s)		(s)
#define HTONL(l)		(l)
#define HTONDL(l)		(l)
#define NTOHS(s)		(s)
#define NTOHL(l)		(l)
#define NTOHDL(l)		(l)
#endif

#define PREOBJ_LEN	( sizeof( uint64_t ) + ( sizeof( uint32_t ) * 4 ) )
#define PREMETA_LEN	sizeof( uint32_t )
#define PRENODE_LEN	sizeof( uint32_t ) * 2
#define PREATTR_LEN	sizeof( uint32_t ) * 3
#define PRENEXT_LEN	sizeof( uint32_t ) * 4
#define PREIA_LEN	PREOBJ_LEN

#define IA_DEPTHNUM	8
#define BUFLEN_8	8
#define BUFLEN_16	16
#define BUFLEN_32	32
#define BUFLEN_64	64
#define BUFLEN_128	128
#define BUFLEN_256	256
#define BUFLEN_512	512

/* used by cmsXml_GetObjectByName(), cmsXml_GetObjectByOID() */
#define NULL_IF_NOT_EXISTED	(1 << 0)
#define ADD_IF_NOT_EXISTED	(1 << 1)
#define CALLOC_IF_EXISTED	(1 << 2)

/* used by cmsXml_SetObjDefault() */
#define OBJECT_RESTORE_DATA		0
#define OBJECT_RESTORE_OBJECT	1
#define OBJECT_CREATE_OBJECT	2

/* used by cmsXmlCallocCounter() */
#define CALLOC_COUNTER_DECREASE	0
#define CALLOC_COUNTER_INCREASE	1
#define CALLOC_COUNTER_DISPLAY	2

/* used by cmsXmlConstructIAValue() */
#define INSTANCE_DEPTH_MAX 7


typedef struct parentList_s{
	struct parentList_s *next;
	struct objectNode_s *node;
}parentList_t;

typedef struct objParameter_s {
	char *name;
	uint32_t	type;
	uint32_t len;
	union{
		sign_t sign;
		unsign_t unsign;
	}max;
	union{
		sign_t sign;
		unsign_t unsign;
	}min;	
	int config;
}objParameter_t;

typedef struct objectList_s
{
	struct objectList_s *next, *prev;
	int OID;
	uint64_t IA;
} objectList_t;

/* ---------- Macros ---------- */
#define	OBJECT_LIST_ENQUEUE(head, node)		\
{											\
	node->next = head;						\
	if(node->next)							\
		while(node->next->next)				\
			node->next = node->next->next;	\
	node->prev = node->next;				\
	node->next = NULL;						\
	if(!head) head = node;					\
	else node->prev->next = node;			\
}

#define	OBJECT_LIST_DEQUEUE(head, node)				\
{													\
	if(node->next) node->next->prev = node->prev;	\
	if(node->prev) node->prev->next = node->next;	\
	else head = node->next;							\
}

#define	OBJECT_LIST_ENQUEUE_BY_DEPTH(head, node)							\
{																			\
	node->prev = NULL;														\
	node->next = NULL;														\
	if(!head){																\
		head = node;														\
	}else{																	\
		node->next = head;													\
		while((node->next)													\
			&& (cmsXmlGetIADepth(node->next->IA) > cmsXmlGetIADepth(node->IA))){	\
			node->prev = node->next;										\
			node->next = node->next->next;									\
		}																	\
		if(node->next)														\
			node->next->prev = node;										\
		if(node->prev)														\
			node->prev->next = node;										\
		else																\
			head = node;													\
	}																		\
}


/* ---------- Macros ---------- */
#define cmsXmlGetUsedShmSize( xmlShmCb ) *( (uint32_t *)( xmlShmCb->baseaddr + sizeof( uint32_t ) * 2 ) )
#define cmsXmlGetStringShmOffset( xmlShmCb ) *( (uint32_t *)( xmlShmCb->baseaddr + sizeof( uint32_t ) * 3 ) )
#define cmsXmlGetPreObjMeta( xmlShmCb, objOffset ) *( (cmsoffset_t *)( ( xmlShmCb->baseaddr + objOffset ) - PREMETA_LEN ) )
#define cmsXmlGetPreObjNode( xmlShmCb, objOffset ) *( (cmsoffset_t *)( ( xmlShmCb->baseaddr + objOffset ) - PRENODE_LEN ) )
#define cmsXmlGetPreObjAttr( xmlShmCb, objOffset ) *( (uint32_t *)( ( xmlShmCb->baseaddr + objOffset ) - PREATTR_LEN ) )
#define cmsXmlGetPreObjNext( xmlShmCb, objOffset ) *( (cmsoffset_t *)( ( xmlShmCb->baseaddr + objOffset ) - PRENEXT_LEN ) )
#ifdef SYSDEF_PARSER_ON_HOST
#define cmsXmlGetPreObjIA( xmlShmCb, objOffset ) *( (uint64_t *)( ( xmlShmCb->baseaddr + objOffset ) - PREIA_LEN ) )
#endif
#define cmsXmlGetIAInfo( x,y ) (uint8_t)( (y<=8 && y)?(((x<<(y-1)*8)>>56)):0 ) /* return type is uint8_t. */
#define cmsXmlGetIADepth( x ) (uint8_t)( ( x > 0 )?( ( x << 56 ) >> 56 ):0 ) /* return type is uint8_t. */


/*object api*/
objectNode_t *cmsXml_getIndexChild(cmsXmlCb_t *xmlShmCb, objectNode_t *node);
int cmsXml_checkObjectChg(cmsXmlCb_t *xmlShmCb, objectNode_t *node);
int cmsXml_copyObjectNodeToNode(cmsXmlCb_t *xmlShmCb, objectNode_t *src, objectNode_t *dst, int flag);


/*parameter api*/
int cmsXml_SearchParameter(cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *parameter, char **meta);
uint16_t cmsXml_getParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter);
parameterValue_t *cmsXml_getParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter);
int cmsXml_setParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter);
int cmsXml_setParameterByParaList(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, paraValueSettingList_t *parameterList);


uint32_t cmsXml_getParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter);
int cmsXml_setParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter, uint32_t flags, int active);
int cms_genCmsFile(cmsXmlCb_t *xmlShmCb, char *xmlPath, char *cmsPath);


/*common api*/
int cmsXml_loadRomToRam(cmsXmlCb_t	*xmlShmCb, const char *filename);
int cmsXml_loadPredefSettingToRam(cmsXmlCb_t *xmlShmCb, const char *filename);
int cmsXml_checkXml(cmsXmlCb_t	*xmlShmCb, const char *filename);
int cmsXml_SaveRamToRom(cmsXmlCb_t *xmlShmCb, const char *filename);
objectNode_t *cmsXml_SearchChildNode( cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *name, uint32_t *namelen);
char *cmsXml_getParameterNamePtr(cmsXmlCb_t *xmlShmCb, objectNode_t *node, int index);
int cmsXml_setNodeStatus(cmsXmlCb_t *xmlShmCb, objectNode_t *node, int active);
cmsoffset_t cmsXmlGetPtrOffset(cmsXmlCb_t *xmlShmCb, void *ptr);
char *cmsXml_getFullPathByID(cmsXmlCb_t * xmlShmCb, cmsoffset_t id);
int cmsXml_freeFullPathBuffer(void **name);
parameterValue_t *cmsXml_getDefaultParameter(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int count, char **parameter);
uint32_t cmsXml_getDefaultParameterAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter);
uint16_t cmsXml_getDefaultParameterExtAttr(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, char *parameter);


void cmsXml_SetCBData( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset );
void cmsXml_SetPreObjNonConfig( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset );
cmsoffset_t cmsXml_SetObjDefault( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset, int flag );
void cmsXml_SetUsedShmSize( cmsXmlCb_t *xmlShmCb, uint32_t objSize );
void cmsXml_SetStringShmOffset( cmsXmlCb_t *xmlShmCb, uint32_t stringSize );
void cmsXml_SetPreObjStatus( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset, int active );
void cmsXml_SortNewObject( cmsXmlCb_t *xmlShmCb, cmsoffset_t srcOffset, cmsoffset_t newOffset );
int cmsXml_GetOIDByTable( cmsoffset_t offset );
cmsoffset_t cmsXml_GetOffsetByOID( int OID );
int cmsXml_GetOIDByOffset( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset );
void *cmsXml_GetFullpathByOIDIA( int OID, uint64_t objIA );
void *cmsXml_GetFullPathByOID(int OID);
int cmsXml_GetOIDMax(void);
void *cmsXml_CallocSpace( cmsXmlCb_t *xmlShmCb, int OID, void *ptr );
int cmsXml_FreeCallocSpace( cmsXmlCb_t *xmlShmCb, int OID, void **object );
int cmsXml_CallocCounter( cmsXmlCb_t *xmlShmCb, int OID, int action );
void *cmsXml_GetObjectByOID( cmsXmlCb_t *xmlShmCb, int OID, uint64_t objIA, int flag );
void *cmsXml_GetObjectByName( cmsXmlCb_t *xmlShmCb, char *name, int flag );
void *cmsXml_AddIndexChildObject( cmsXmlCb_t *xmlShmCb, int OID, uint64_t nodeIA );
void *cmsXml_AddObjectWithAssignIA( cmsXmlCb_t *xmlShmCb, int OID, uint64_t IA );
int cmsXml_DelObject( cmsXmlCb_t *xmlShmCb, int flag );
int cmsXml_DelObjectByOID( cmsXmlCb_t *xmlShmCb, int OID, uint64_t IA );
int cmsXml_DelObjectByName( cmsXmlCb_t *xmlShmCb, char *name );
int cmsXml_DelObjectByOffset( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset );
int cmsXml_CheckDelObject( cmsXmlCb_t *xmlShmCb, objectNode_t *node, int OID, uint64_t IA );
objectList_t *cmsXml_GetObjListByName( cmsXmlCb_t *xmlShmCb, char *name );
objectList_t *cmsXml_GetObjListByOID( cmsXmlCb_t *xmlShmCb, int OID );
objectList_t *cmsXml_GetObjListByOIDIA( cmsXmlCb_t *xmlShmCb, int OID, uint64_t IA, int depth );
objectList_t *cmsXml_GetFullChildList( cmsXmlCb_t *xmlShmCb, int OID, uint64_t IA );
objectList_t *cmsXml_GetOneLayerChildList( cmsXmlCb_t *xmlShmCb, int OID, uint64_t IA );
objectList_t *cmsXml_CreateObjListNode( int OID, uint64_t IA );
void cmsXml_FreeObjListNode( objectList_t** objList, int OID, uint64_t IA );
void cmsXml_FreeObjList( objectList_t** objList );
int cmsXml_GetObjectChildList( cmsXmlCb_t *xmlShmCb, objectNode_t *node, int OID, uint64_t IA, objectList_t **list );
int cmsXml_GetObjChildList_OneLayer( cmsXmlCb_t *xmlShmCb, objectNode_t *node, int OID, uint64_t IA, objectList_t **list );
void cmsXml_CheckIndexChildSibling( cmsXmlCb_t *xmlShmCb, objectNode_t *node, uint64_t IA );
void cmsXml_CheckIndexChildParents( cmsXmlCb_t *xmlShmCb, objectNode_t *node, uint64_t IA );
void **cmsXml_GetParameterNameByObjectName(cmsXmlCb_t *xmlShmCb, char *objectPath);

uint64_t cmsXmlSetIAValue( uint64_t originalValue, int index, uint64_t setValue );
int compareIAByDepth( uint64_t a, uint64_t b, uint8_t depth );
int compareIAOrder( uint64_t a, uint64_t b );
void printIAArray( uint64_t value );
void printIANext( cmsXmlCb_t *xmlShmCb, cmsoffset_t offset );
void printUsedCallocCounter( cmsXmlCb_t *xmlShmCb, objectNode_t *node );

#ifndef SYSDEF_PARSER_ON_HOST
unsigned long long HTONLL( unsigned long long src );
unsigned long long NTOHLL( unsigned long long src );
uint64_t cmsXmlGetPreObjIA( cmsXmlCb_t *xmlShmCb,cmsoffset_t objOffset );
#endif

int cmsXml_CopyRdmObjectNodeToDstRdmNode(cmsXmlCb_t *srcrdmCB, cmsXmlCb_t *dstrdmCB,objectNode_t *src, objectNode_t *dst, int flag);

#endif

